#pragma once
#include <list>
using namespace std;

#include "Edge.h"

enum VertexType {RED, BLUE, GREEN, GRAY, CLEAR};

class Vertex
{
private:
	list <Edge*>			edges;
	list <Edge*>::iterator	lastEdgeUseIterator;

	int						lastEdgeUse;

public:
	VertexType				Type;
	string					data;
	int						usingCount;

	Vertex()
	{
		Type		= CLEAR;
		lastEdgeUse = -5;
		lastEdgeUseIterator = edges.begin();

		usingCount	= 0;
	}

	void		addEdge (Edge* new_Edge)
	{
		edges.push_back(new_Edge);
	}

	Vertex*		goTo(int index, bool Directed)
	{
		if(index < 0 || index >= edges.size())
			return NULL;

		if(lastEdgeUse == index)
			return (*lastEdgeUseIterator) -> getOtherVertex (this, Directed);

		if(lastEdgeUse + 1 == index)
		{
			lastEdgeUse++;
			lastEdgeUseIterator++;
			return (*lastEdgeUseIterator) -> getOtherVertex (this, Directed);
		}


		if(lastEdgeUse - 1 == index)
		{
			lastEdgeUse--;
			lastEdgeUseIterator--;
			return (*lastEdgeUseIterator) -> getOtherVertex (this, Directed);
		}

		int			from_begin	= index,
					from_end	= edges.size() - index - 1,
					from_it		= abs(lastEdgeUse - index);

		lastEdgeUse = index;

		if(from_begin <= from_end && from_begin <= from_it)
		{
			lastEdgeUseIterator = edges.begin();

			for(int q=0; q<index; q++)
				lastEdgeUseIterator++;


			return (*lastEdgeUseIterator) -> getOtherVertex (this, Directed);
		}

		if(from_end <= from_begin && from_end <= from_it)
		{
			lastEdgeUseIterator = --edges.end();

			for(int q=edges.size()-1; q>=index; q--)
				lastEdgeUseIterator--;

			return (*lastEdgeUseIterator) -> getOtherVertex (this, Directed);
		}

		if(from_it <= from_begin && from_it <= from_end)
		{
			bool	need_plus = lastEdgeUse < index;

			while(lastEdgeUse != index)
			{
				if(need_plus)
				{
					lastEdgeUse++;
					lastEdgeUseIterator++;
				}
				else
				{
					lastEdgeUse--;
					lastEdgeUseIterator--;
				}
			}
			return (*lastEdgeUseIterator) -> getOtherVertex (this, Directed);
		}
	}
	Edge*		getLastUseEdge()
	{
		return *lastEdgeUseIterator;
	}

	void		setName(int new_Name)
	{
		char buffer[32];
		itoa(new_Name, buffer, 10);
		data = string(buffer);
	}
	void		deletEdge(Edge *Delet)
	{
		list <Edge*> :: iterator It = edges.begin();
		for(int q=0; q<edges.size(); q++, It++)
		{
			if(*Delet == **It)
			{
				edges.erase (It);
				lastEdgeUseIterator = edges.begin();
				lastEdgeUse			= 0;

				break;
			}
		}
	}
	void		deletMe(bool Directed)
	{
		list <Edge*> :: iterator It = edges.begin();
		for(int q=0; q<edges.size(); q++, It++)
			(*It) ->getOtherVertex(this, Directed) -> deletEdge(*It);
	}
	int			edgesCount()
	{
		return edges.size();
	}
	Edge*		getEdgeWhoGoTo(Vertex* search)
	{
		list <Edge*> :: iterator It = edges.begin();
		for(int q=0; q<edges.size(); q++, It++)
		{
			if ( (*It) -> getOtherVertex (this, false) == search)
				return *It;
		}

		return NULL;
	}
	EdgeType	getEdgeType (int index)
	{
		if(index < 0 || index >= edges.size())
			return eCLEAR;

		if(lastEdgeUse == index)
			return (*lastEdgeUseIterator) -> Type;

		if(lastEdgeUse + 1 == index)
		{
			lastEdgeUse++;
			lastEdgeUseIterator++;
			return (*lastEdgeUseIterator) -> Type;
		}


		if(lastEdgeUse - 1 == index)
		{
			lastEdgeUse--;
			lastEdgeUseIterator--;
			return (*lastEdgeUseIterator) -> Type;
		}

		int			from_begin	= index,
					from_end	= edges.size() - index - 1,
					from_it		= abs(lastEdgeUse - index);

		lastEdgeUse = index;

		if(from_begin <= from_end && from_begin <= from_it)
		{
			lastEdgeUseIterator = edges.begin();

			for(int q=0; q<index; q++)
				lastEdgeUseIterator++;


			return (*lastEdgeUseIterator) -> Type;
		}

		if(from_end <= from_begin && from_end <= from_it)
		{
			lastEdgeUseIterator = --edges.end();

			for(int q=edges.size()-1; q>=index; q--)
				lastEdgeUseIterator--;

			return (*lastEdgeUseIterator) -> Type;
		}

		if(from_it <= from_begin && from_it <= from_end)
		{
			bool	need_plus = lastEdgeUse < index;

			while(lastEdgeUse != index)
			{
				if(need_plus)
				{
					lastEdgeUse++;
					lastEdgeUseIterator++;
				}
				else
				{
					lastEdgeUse--;
					lastEdgeUseIterator--;
				}
			}
			return (*lastEdgeUseIterator) -> Type;
		}
	}
};

// -=BAIZOR=-